home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld: Complete Mac Interactive
/
Macworld Complete Mac Interactive CD)(1994).iso
/
The Best of BMUG
/
Utilities
/
Text and Speech
/
Alpha.5.76
/
Tcl
/
SystemCode
/
procs.tcl~
< prev
next >
Wrap
Text File
|
1994-03-08
|
17KB
|
714 lines
#==============================================================================
proc normalLeftBracket {} {
insertText "\{"
}
proc normalRightBracket {} {
insertText "\}"
}
bind '\[' <zs> normalLeftBracket
bind '\]' <zs> normalRightBracket
# Select the next or current word. If word already selected, will go to next.
proc hiliteWord {} {
if {[getPos]!=[selEnd]} forwardChar
forwardWord
set start [getPos]
backwardWord
select $start [getPos]
}
bind 'h' <z> hiliteWord
#================================================================================
# Mode variables
#================================================================================
# For mark stack.
set markName 0
set markStack ""
# mapping of windows to current modes.
set winModes("") ""
# making vars local to windows
set localVars { optionIsMeta wordBreak wordBreakPreface wordWrap
fillColumn leftFillColumn tabSize elecLBrace elecRBrace electricSemi
prefixString suffixString funcExpr funcPar sortedIsDefault
markSorting }
# 'incomingVars' used to hold old var values that have been overwritten in current window
#================================================================================
# Handle 'flag' and 'var' menu selections.
#================================================================================
proc editFlag {menu item} {
global $item localVars incomingVars
set val [expr ([set $item]-1)*-1]
set $item $val
}
proc editVar {menu item} {
global $item localVars incomingVars
append prmpt "New Value of " $item ": "
if ![catch {prompt $prmpt [set $item]} res] {
set $item $res
}
}
#=============================================================================
# Hook procs recognized: "openHook", "closeHook", "activateHook", "deactivateHook",
# "suspendHook", "saveasHook", "saveHook", and "resumeHook".
#=============================================================================
# Event hooks - set specific modes when files opened.
proc openHook name {
global winModes
$winModes($name)
if {$name == {*Toolserver shell*}} startMPW
addWinName $name
}
# full pathname
proc saveHook name {
global backup backExtension backDir
if {![string length [set dir $backDir]]} {
set dir [file dirname $name]
}
if ($backup) {
catch {rm $dir:[file tail $name]~}
cp $name $dir:[file tail $name]$backExtension
}
}
# Clean up the mark stack.
proc closeHook name {
global markStack
global winModes
unset winModes($name)
if [llength $markStack] {
set markStack [removePat $markStack $name*]
}
removeWinName $name
}
proc saveasHook {oldName newName} {
global winModes
removeWinName $oldName
addWinName $newName
setWinMode $newName
$winModes($newName)
}
proc activateHook name {
global winModes
if {[catch {$winModes($name)}]} {
setWinMode $name
$winModes($name)
}
}
proc dirtyHook {name dirty} {
markMenuItem Wins [file tail $name] $dirty "◊"
}
#================================================================================
proc setWinMode name {
global winModes
set nm [file tail $name]
if {[set first [string last " <" $name]] >= 0} {
set rname [string range $name 0 [expr $first - 1]]
} else {
set rname $name
}
case $rname in {
"*.c" { set winModes($name) setCMode }
"*.tex" { set winModes($name) setTexMode; winFuncTitle $nm "Sect" }
"*.cc" { set winModes($name) setC++Mode; winFuncTitle $nm "Meth" }
"*.cp" { set winModes($name) setC++Mode; winFuncTitle $nm "Meth" }
"*.C" { set winModes($name) setC++Mode; winFuncTitle $nm "Meth" }
"*.h" { set winModes($name) setCMode }
"*.f" { set winModes($name) setFortranMode }
"*.tcl" { set winModes($name) setTclMode; winFuncTitle $nm "Proc" }
{*Toolserver\ sh*} { set winModes($name) setMPWMode; winFuncTitle $nm "Proc" }
{*tcl\ sh*} { set winModes($name) setShellMode; winFuncTitle $nm "Proc" }
"*.sty" { set winModes($name) setTexMode; winFuncTitle $nm "Sect" }
"Browser" { set winModes($name) setBrowseMode }
default { set winModes($name) setTextMode }
}
}
# 'modes' is inspected by alpha for the popup mode menu. 'newMode' is
# called by Alpha in case of a successful choice.
set modes { C C++ Csh Fort MPW Tcl TeX Text }
set modeProcs(C) setCMode
set modeProcs(C++) setC++Mode
set modeProcs(Csh) setShellMode
set modeProcs(Fort) setFortranMode
set modeProcs(MPW) setMPWMode
set modeProcs(Tcl) setTclMode
set modeProcs(TeX) setTexMode
set modeProcs(Text) setTextMode
proc newMode mode {
global winModes
global modeProcs
set name [lindex [winNames -f] 0]
$modeProcs($mode)
set winModes($name) $modeProcs($mode)
}
proc deactivateHook name {
}
proc suspendHook name {
global iconifyOnSwitch
global suspIconed
if {$iconifyOnSwitch} {
set wins [winNames -f]
foreach win $wins {
if {![icon -f "$win" -q]} {
set suspIconed($win) 1
icon -f "$win" -t
}
}
}
}
proc resumeHook name {
global iconifyOnSwitch resumeRevert suspIconed
if {$iconifyOnSwitch && [info exists suspIconed]} {
set wins [winNames -f]
foreach win [array names suspIconed] {
icon -f "$win" -o
}
unset suspIconed
}
if {$resumeRevert} {
set resumeRevert 0
revert
}
}
# Handles dynamically adding and deleting window names from menu.
proc addWinName name {
global winNameToNum
global winNumToName
global fullNames
for {set i 0} {$i<100} {incr i} {
if {[catch {set nm $winNumToName($i)} res] == "1"} {
if {$fullNames != "0"} {
set nm $name
} else {
regexp {[^:]*$} $name nm
}
if {$i < 10} {
addMenuItem -m -l "/$i" Wins $nm
} else {
addMenuItem -m -l "" Wins $nm
}
set winNumToName($i) $name
set winNameToNum($name) $i
return
}
}
}
proc removeWinName name {
global winNameToNum
global winNumToName
global fullNames
set num $winNameToNum($name)
unset winNumToName($num)
unset winNameToNum($name)
if {$fullNames == "1"} {
deleteMenuItem -m Wins $name
} else {
regexp {[^:]*$} $name nm
deleteMenuItem -m Wins $nm
}
}
proc menuWin {menu name} {
global winNameToNum
set nms [array names winNameToNum]
foreach nm $nms {
if {[string match *$name $nm] == "1"} {
bringToFront $name
if [icon -q] { icon -f $name -o }
return
}
}
return "normal"
}
set lastMode 0
# rta Creating texWasLast variable
set texWasLast 0
# rta Following changed from ThinkC to MPW
# Modes
# Fortran programming mode
proc setFortranMode {} {
changeMode "Fort"
uplevel #0 {
set elecLBrace 0
set elecRBrace 0
set electricSemi 0
set wordWrap 0
set funcExpr {^( |\t)(subroutine|.*function|SUBROUTINE|.*FUNCTION).*\(.*$}
set sortedIsDefault 0
}
}
# Ordinary, default mode
proc setTextMode {} {
changeMode "Text"
uplevel #0 {
set elecLBrace 0
set elecRBrace 0
set electricSemi 0
set wordWrap 1
set prefixString "> "
set suffixString " <--"
}
}
#================================================================================
# Instantiate a global variable to the path of a file (usually an app). As a
# side-effect, make the instantiation permanent by adding a line to 'definitions.tcl'.
proc addAppPath {name var} {
global $var
if {[catch {getfile "Find '$name' app:"} path]} {return 1}
set $var $path
addUserLine "set $var \"[quoteExpr2 $path]\""
return 0
}
proc addUserLine {line} {
global HOME
if {[file exists "$HOME:userStartup.tcl"]} {
set fid [open "$HOME:userStartup.tcl" "a"]
} else {
set fid [open "$HOME:userStartup.tcl" "w"]
}
puts $fid $line
close $fid
}
proc getFileSig {f} {
catch {lindex [ls -l $f] 5} var
return $var
}
# Look for given app sig in active processes. If not there, try to
# launch with 'path' prompting for 'path' if necessary.
# Return the real name of the app. Don't switch.
proc checkRunning {name sig path} {
global $path
foreach proc [processes] {
if {[lindex $proc 1] == $sig} {
return [lindex $proc 0]
}
}
if {![info exists $path] || ![file exists [set $path]]} {
if {[addAppPath $name $path]} return
}
if {[catch {getFileSig [set $path]}]} {
if {[addAppPath $name $path]} return
}
set sig [getFileSig [set $path]]
if {[catch {launch -f [set $path]}]} {
error "Problem with script."
}
return [file tail [set $path]]
# return [checkRunning $name $sig $path]
}
#================================================================================
# Excalibur is the only Mac spell-checker that I know of which will handle LaTeX as
# well as ordinary text.
proc spellcheckWindow {} {
global excaliburPath resumeRevert
catch {checkRunning Excalibur XCLB excaliburPath} name
if {[winInfo dirty]} {
if {[askyesno "Save '[lindex [winNames] 0]'?"] == "yes"} {
save
}
}
if {[catch {sendOpenEvent -n $name [lindex [winNames -f] 0]}] } {
beep
} else {
switchTo $name
}
set resumeRevert 1
}
proc spellcheckSelection {} {
global excaliburPath
catch {checkRunning Excalibur XCLB excaliburPath} name
if {[getPos] == [selEnd]} {
beep
message "No selection"
return;
}
copy
switchTo $name
}
menu -n $excaliburMenu {
"spellcheckWindow"
}
insertMenu $excaliburMenu
#================================================================================
proc changeMode {newMode} {
global lastMode
global savedIsMeta
global wordBreak
global wordBreakPreface
global optionIsMeta
global latexMenu excaliburMenu thinkMenu toolserverMenu
displayMode $newMode
if {$lastMode == $newMode} return
case $lastMode in {
"Tex" {
set optionIsMeta $savedIsMeta
set wordBreakPreface {[^a-zA-Z0-9_]}
set wordBreak {[a-zA-Z0-9_]+}
set optionIsMeta 1
catch {removeMenu $latexMenu}
insertMenu $excaliburMenu
}
"Csh" {
catch {removeMenu "Tcl"}
}
"Tcl" {
catch {removeMenu "Tcl"}
}
"BRWZ" {
catch {removeMenu "Browse"}
}
"C" {
catch {removeMenu $thinkMenu}
catch {removeMenu $toolserverMenu}
}
"C++" {
catch {removeMenu $thinkMenu}
catch {removeMenu $toolserverMenu}
}
}
global mode
set mode $newMode
set lastMode $newMode
}
proc alphaHelp {} {
global HOME
edit -r -m "$HOME:Help: Intro "
}
proc tclHelp {} {
global HOME
edit -r -m "$HOME:Help: Tcl Manual"
}
set patternLibrary {
{ "Pascal to C Comments" { \{([^\}]*)\}} {/* \1 */} }
{ "C++ to C Comments" {//(.*)} {/* \1 */}}
}
proc dividingLine {} {
insertText "================================================================================\r"
}
bind 'l' <C> dividingLine
proc texDividingLine {} {
insertText "%================================================================================\r"
}
bind 'l' <C> texDividingLine TeX
proc cDividingLine {} {
insertText "//================================================================================\r"
}
bind 'l' <C> cDividingLine C
bind 'l' <C> cDividingLine C++
proc tclDividingLine {} {
insertText "#================================================================================\r"
}
bind 'l' <C> tclDividingLine Tcl
#================================================================================
if {[catch {info args oldCd}]} {
rename cd oldCd
}
proc cd args {
global HOME
if {[llength $args]} {
oldCd [string trim [eval list $args] " \{\}"]
} else {
oldCd $HOME
}
}
#================================================================================
proc getVarValue {} {
set val [listpick -p {Which var?} [lsort [info globals]]]
if {![string length $val]} return
global $val
alertnote [join [list "'$val' = " [set $val]] ""]
}
#================================================================================
proc selectParagraph {} {
set pos [getPos]
set start [paraStart $pos]
set finish [paraFinish $pos]
goto $start
select $start $finish
}
# wrapText == getText ; breakIntoLines ; replaceText
# Remove text from window, transform (join, del-ws), insert back into window.
proc fillTextByPar {from to} {
set text [getText $from $to]
regsub -all "\r(\[ \t\]*\r)+" $text "\r\r\r" text
regsub -all "(\[^\r\])\r" $text "\\1 " text
regsub -all "\[ \t\]+" $text " " text
return [breakIntoLines $text]
}
proc fillRegionByPar {{start -1} {finish -1}} {
# # if {[getPos] == [selEnd]} { return}
if {($start < 0) || ($finish < 0)} {
set start [lineStart [getPos]]
set finish [selEnd] }
if {$start >= $finish} return
goto $start
set text [fillTextByPar $start $finish]
replaceText $start $finish $text "\r"
}
#
# join Lines in region -- if no optional args, use selection
#
proc joinRegion {{from -1} {to -1}} {
if {($from < 0) || ($to < 0)} { set from [getPos] ; set to [selEnd] }
if {$from >= $to} return
set text [getText $from $to]
regsub -all "\r(\[ \t\]*\r)+" $text "\r\r\r" text
regsub -all "(\[^\r\])\r" $text "\\1 " text
replaceText $from $to $text "\r"
}
# WARNING: regsub ^$ refers to string endpts (not lines)
# FUTURE: filterLines like perl:
# replaceText[apply_to_all(cmd,split [getText [getPos] [selEnd]] "\r")]
# OR: replaceInRegion: dup_\r, $=>\r ??
#
#
# Remove text from window, transform (delete dup ws), insert back into window.
#
# inputs: message, alertnote, askyesno, listpick, prompt KILLS SELECTION.
# search: bnds = search -forward -regExpr -ignoreCase -matchWords -noabort
# -l limit pat pos
#
proc regsubInRegion {from to srch repl} {
if {![string length $srch]} return
if {$from >= $to} return
set text [getText $from $to]
regsub -all "$srch" $text "$repl" text
replaceText $from $to $text
}
# while {($pos < $to) &&
# ![catch {search -f 1 -r 1 -i 1 -m 0 "$srch" $pos} mtch]} {
# set mbeg [lindex $mtch 0]
# set pos [lindex $mtch 1]
# replaceText $mbeg $pos $repl }
proc backSlashSub {arg} { eval [concat return "\"$arg\""] }
proc replaceInRegion {} {
if [catch {prompt "Search RegExpr:" ""} srch] return
if [catch {prompt "Replace String:" ""} repl] return
if {![string length $srch]} return
regsubInRegion [getPos] [selEnd] \
[backSlashSub "$srch"] [backSlashSub "$repl"]
}
#
# Apply command to each line (or paragraph) in selection ;
# if no cmd arg then prompts for it
#
proc filterLines {{cmd 0} {parunit 0}} {
if {$cmd == 0} {
if {[catch { prompt "Line-filter command: " "" } cmd]} { return } }
if {![string length $cmd]} return
set unitStart lineStart
set unitEnd nextLineStart
if {$parunit} {
set unitStart paraStart
set unitEnd paraFinish }
set pos [$unitStart [getPos]]
set finish [selEnd]
if {$pos >= $finish} return
goto $pos
createTMark "filterLend" $finish
set next [$unitEnd $pos]
while {(($next > $pos) && ($pos < $finish))} {
goto $next
createTMark "filterLnext" $next
setMark
goto $pos
if {[catch [list uplevel #0 "$cmd"] retval]} { altertnote $retval }
set finish [getTMark "filterLend"]
gotoTMark "filterLnext"
set pos [$unitStart [getPos]]
set next [$unitEnd $pos]]
}
removeTMark "filterLend"
removeTMark "filterLnext"
}
proc filterParagraphs {{cmd 0}} { filterLines $cmd 1 }
# WARNING: deselecting sets the mark to selEnd
proc sortParagraphs {{from -1} {to -1}} {
if {($from < 0) || ($to < 0)} { set from [getPos] ; set to [selEnd] }
if {$from >= $to} return
joinRegion {$from $to}
select [getPos] [nextLineStart [getMark]]
sortLines
select [getPos] [getPos]
regsubInRegion [getPos] [getMark] "\r" "\r\r"
wrapRegion
}
#
# Sample
#
proc filterRegion {{from -1} {to -1} {cmd 0} {newwin 0}} {
if {$cmd == 0} {
if {[catch { prompt "Eval command: " "" } cmd]} { return }
}
if {![string length $cmd]} return
if {($from < 0) || ($to < 0)} { set from [getPos] ; set to [selEnd] }
if {$from >= $to} return
set pos [getPos]
set text [getText $from $to]
set text [$cmd $text]
replaceText $from $to $text "\r"
goto $pos
}
#===========================
# ==== FUNCTIONS (COMMANDS)
#===========================
# ==== Redo History ====
set evalLastCmd ""
# Eval one command --- "eval" vs. "catch"
# # catch: 0_OK == catch cmd retval
# # set retval [eval [list uplevel #0 "$cmd"]]
# # catch [list uplevel #0 "$cmd"] retval
#
proc evalCommand {} {
global evalLastCmd
if {![catch { prompt "Eval command: " "" } cmd]} {
set evalLastCmd $cmd
set retval [eval [list uplevel #0 "$cmd"]]
message $retval }
}
proc evalToText {} {
global evalLastCmd
if {![catch { prompt "Eval command: " "" } cmd]} {
set evalLastCmd $cmd
catch [list uplevel #0 "$cmd"] retval
getline "Result:" "$retval" }
}
# repeat complex command
proc repeatEval {} {
global evalLastCmd
set cmd $evalLastCmd
if {$cmd == ""} { abortEm ; return }
set retval [eval [list uplevel #0 "$cmd"]]
message $retval
}
# Escape current mode for one command
proc execCommand {} {
global mode
set saveMode $mode
changeMode "Text"
execute
changeMode $saveMode
}
# First, define macros to bypass the electric braces.
proc ordLeftBrace {} {
insertText " \{"
}
bind {'['} <cs> ordLeftBrace
proc ordRightBrace {} {
insertText "\}"
blink [matchIt "\}" [expr [getPos]-1]]
}
bind {']'} <cs> ordRightBrace
proc quoteWord {} {
backwardWord
insertText "'"
forwardWord
insertText "'"
}
bind ''' <z> quoteWord